package com.yangyang.ralearn.common;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

import org.apache.log4j.Logger;
import org.codehaus.groovy.control.CompilationFailedException;

import com.yangyang.ralearn.client.rlclient.IRLAgentHandler;
import com.yangyang.ralearn.common.entity.base.AbstractDomainPredicate;
import com.yangyang.ralearn.common.entity.base.BaseAction;
import com.yangyang.ralearn.common.entity.base.BaseActionModelDef;
import com.yangyang.ralearn.common.entity.base.BasePredicate;
import com.yangyang.ralearn.common.exception.AlgorithmEndException;
import com.yangyang.ralearn.common.types.JType;

/**
 * 所有算法都要实现这个抽象类
 * 
 * @author yangyang
 * 
 */
public abstract class BaseAlgorithm {

	private static GroovyClassLoader loader = new GroovyClassLoader(
			BaseAlgorithm.class.getClassLoader());
	private static Class<?> groovyClass = null;
	private static GroovyObject object = null;
	static {
		try {
			groovyClass = loader
					.parseClass(new File(
							"src/com/yangyang/ralearn/common/script/BaseAlgorithm.groovy"));
			object = (GroovyObject) groovyClass.newInstance();
		} catch (CompilationFailedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	protected Map<String, Set<BaseActionModelDef>> mapName2Models;

	protected void removeAllActionModels(String name,
			Set<BaseActionModelDef> models) {
		synchronized (this) {
			if (name.equals("pick-up") || name.equals("put-down")) {
				int a = 1;
				a++;
			}
			this.mapName2Models.get(name).removeAll(models);
		}
	}

	protected void removeActionModel(String name, BaseActionModelDef model) {
		synchronized (this) {
			if (name.equals("pick-up") || name.equals("put-down")) {
				int a = 1;
				a++;
			}
			this.mapName2Models.get(name).remove(model);
		}
	}

	/**
	 * 算法执行的主函数
	 * 
	 * @throws AlgorithmEndException
	 */
	public abstract void run(IRLAgentHandler handler)
			throws AlgorithmEndException;

	/**
	 * 根据给定的动作模型参数初始化所有的action-model
	 * 
	 * @param actions
	 */
	public void init(JEnvironment environment,
			Map<String, Map<String, String>> actions) {
		this.mapName2Models = new ConcurrentHashMap<String, Set<BaseActionModelDef>>();
		for (Entry<String, Map<String, String>> entry : actions.entrySet()) {
			Map<String, JType> map = new HashMap<String, JType>();
			for (Entry<String, String> item : entry.getValue().entrySet()) {
				map.put(item.getKey(),
						environment.mapNameType.get(item.getValue()));
			}
			Set<BaseActionModelDef> models = new CopyOnWriteArraySet<BaseActionModelDef>(
					this.getAllPossiableActionModel(environment,
							entry.getKey(), map));
			this.mapName2Models.put(entry.getKey(), models);
			Logger.getLogger(BaseAlgorithm.class).debug(models);

		}
	}

	/**
	 * 根据一个ActionModel和当前的状态获取所有可以执行的动作
	 * 
	 * @param def
	 * @param currentStates2
	 * @return
	 */
	@SuppressWarnings("unchecked")
	protected Set<BaseAction> getAllPossiableAction(BaseActionModelDef def,
			List<AbstractDomainPredicate> currentStates2) {
		return (Set<BaseAction>) object.invokeMethod("getAllPossiableAction",
				new Object[] { def, currentStates2 });
	}

	/**
	 * 根据动作名称和参数枚举所有理论上可能的actionmodel
	 * 
	 * @param name
	 * @param types
	 * @return
	 */

	@SuppressWarnings("unchecked")
	protected Set<BaseActionModelDef> getAllPossiableActionModel(
			JEnvironment environment, String name, Map<String, JType> types) {
		return (Set<BaseActionModelDef>) object.invokeMethod(
				"getAllPossiableActionModel", new Object[] { environment, name,
						types });
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder("basealgorithm version 1.0\n");
		sb.append(this.getName());
		return sb.toString();
	}

	/**
	 * 获取算法的名称
	 * 
	 * @return
	 */
	public abstract String getName();

	/**
	 * 根据具体的规划定义过滤掉不符合但理论上可行的部分规划，减少规划的动作模型空间。
	 */
	public abstract void filter(IRLAgentHandler handler);

	public static void main(String[] args) {

		/*
		 * final String domainFile = "bin/domain1.pddl"; final String
		 * problemFile = "bin/problem1.pddl";
		 * Logger.getLogger(BaseServer.class).info( "domain:" + domainFile +
		 * ",problem:" + problemFile); PlanParser domainParser = null;
		 * ProblemParser problemParser = null; try { domainParser = new
		 * PlanParser(new FileInputStream(domainFile));
		 * domainParser.domain_def(); } catch (FileNotFoundException e) { //
		 * TODO Auto-generated catch block e.printStackTrace(); return; } catch
		 * (com.yangyang.ralearn.server.parser.ParseException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); } try { problemParser
		 * = new ProblemParser(new FileInputStream(problemFile));
		 * problemParser.problem_def(); } catch (FileNotFoundException e) { //
		 * TODO Auto-generated catch block e.printStackTrace(); return; } catch
		 * (com.yangyang.ralearn.common.parser.ParseException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); return; }
		 * 
		 * System.out.println(BaseAlgorithm.groovyClass);
		 * 
		 * BaseAlgorithm algorithm = new BaseAlgorithm() {
		 * 
		 * @Override public void run() throws AlgorithmEndException { // TODO
		 * Auto-generated method stub
		 * 
		 * }
		 * 
		 * @Override public String getName() { // TODO Auto-generated method
		 * stub return null; }
		 * 
		 * @Override public void filter() { // TODO Auto-generated method stub
		 * 
		 * } };
		 * 
		 * Map<String, Map<String, String>> actions = new HashMap<String,
		 * Map<String, String>>(); { Map<String, String> params = new
		 * HashMap<String, String>(); params.put("?x", "block");
		 * actions.put("pick-up", params); } algorithm.init(actions);
		 * Logger.getLogger(BaseAlgorithm.class).debug(
		 * algorithm.getAllPossiableAction(
		 * JEnvironment.instance().mapNameActionModelDef .get("stack"),
		 * JSimulator.Simulator.currentStates));
		 */
	}
}
